package com.yhx.security.demo;

import org.springframework.util.Base64Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @version 1.0
 * @Author zhangxiaoli5
 * @Description RSA加解密工具
 * @Date 2019/8/9 15:39
 **/
public class RSAUtils {
    private RSAUtils() {
    }

    public static byte[] encryptByPublicKey(String data, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
        PublicKey publicKey = buildPublicKey(key);
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(1, publicKey);
        byte[] encryptData = cipher.doFinal(data.getBytes(Charset.forName("UTF-8")));
        return encryptData;
    }

    public static byte[] encryptByPublicKey(byte[] data, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
        PublicKey publicKey = buildPublicKey(key);
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(1, publicKey);
        byte[] encryptData = cipher.doFinal(data);
        return encryptData;
    }

    public static byte[] decryptByPublicKey(byte[] data, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
        PublicKey publicKey = buildPublicKey(key);
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(2, publicKey);
        return cipher.doFinal(data);
    }

    public static byte[] encryptByPrivateKey(String data, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
        return encryptByPrivateKey(data.getBytes(Charset.forName("UTF-8")), key);
    }

    public static byte[] encryptByPrivateKey(byte[] data, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
        PrivateKey privateKey = buildPrivateKey(key);
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(1, privateKey);
        return cipher.doFinal(data);
    }

    public static byte[] decryptByPrivateKey(byte[] data, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
        PrivateKey privateKey = buildPrivateKey(key);
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(2, privateKey);
        return cipher.doFinal(data);
    }

    private static PublicKey buildPublicKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] keyBuffer = Base64Utils.decodeFromString(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBuffer);
        return keyFactory.generatePublic(keySpec);
    }

    private static PrivateKey buildPrivateKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] keyBuffer = Base64Utils.decodeFromString(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBuffer);
        return keyFactory.generatePrivate(keySpec);
    }
}
